namespace TheGunningMan

import System
import Gunningine

// All game states are defined here.  Some are subclassed from built-in states such as Load, Play, LoadLevel, Menu, etc.

//
// TheGunningMan game
//
class TheGunningManGame(IGame):

    // This is the entry-point into the game.  We return an instance of the state that we want to start in.
    InitialState as GameState:
        get: return StateLoad()

//
// Load state.  This is subclassed from the existing state.
//
class StateLoad(GameStateLoad):

    //
    // Once the state's base update has done, check to see if we're ready to move on.
    //
    protected override def UpdatePost():
        if ResourcesLoaded:
            ChangeState(StatePlay())

//
// Play state.
//
// The host code has methods for the following:
// Camera
// Map
// Entity
//
// In each case, you can create, manipulate and query these objects, and store references
// to them in the script, however they are updated in host code.  In other words, the idea
// is to give the scripting a small set of core objects to create the game out of.
// Thus, these classes need a defined script inteface, and to have their host methods
// declared as internal.
//
// Debugging should be done by toggling debug mode, and this then lets you edit various
// game variables, such as camera positioning.
//
class StatePlay(GameStatePlay):
    
    //
    // Enter state.
    //
    protected override def EnterPost():

        // Create map, and ground texture for it.
        gameMap = CreateMap(64, 64, 32)
        
        Gfx.CreateRenderTexture("Ground", 64 * 32, 64 * 32, 3)

        // Create player
        playerPos = Vector3(gameMap.SizeX / 2, gameMap.SizeY / 2, 0)        
        CreatePlayer("QuakeGuy", playerPos, Vector3.UnitY)

        // Create cameras, pointing at player
        CreateCamera(Vector3.Zero, Vector3.Zero, Vector3.Zero)
        UpdateCamera(self.Player.Position + self.Player.Direction)
        
        // Add some random enemies
        enemyNames as (string) = ("Demon", "Dog", "Knight", "Hellknight", "Ogre", "Shambler", "Vore")
        r = Random()
        
        for i in range(1000):
            enemyPos = gameMap.GetRandomSpawnLocation(r)
            enemyDir = (self.Player.Position - enemyPos).Normalised()
            
            enemyType = enemyNames[r.Next(enemyNames.Length)]
            CreateEntity(enemyType, enemyPos, enemyDir, 1)

    //
    // Update state.
    //
    protected override def UpdatePost():
        
        if Input.IsKeyPressed(KeyCode.Escape):
            ExitState()
        if Input.IsKeyPressed(KeyCode.F11):
            ToggleDebugCamera()
        if Input.IsKeyPressed(KeyCode.F12):
            ToggleDebugText()
        
        // Movement
        playerMovement = Vector3.Zero

        if Input.IsKeyDown(KeyCode.Left):
            playerMovement += Vector3.NegativeUnitX
        if Input.IsKeyDown(KeyCode.Right):
            playerMovement += Vector3.UnitX
        if Input.IsKeyDown(KeyCode.Up):
            playerMovement += Vector3.UnitY;
        if Input.IsKeyDown(KeyCode.Down):
            playerMovement += Vector3.NegativeUnitY

        playerMovement.Normalise()
        self.Player.Move(playerMovement)

        CalculateAimingTarget(Input.MouseX, Input.MouseY);

        // Turn player to face target, and update camera.
        targetNormalised = (self.WorldAimingTarget - self.Player.Position).Normalised();
        angleToTarget = 90.0f - MathsUtils.RadToDeg(Math.Atan2(targetNormalised.Y, targetNormalised.X));
        self.Player.SetFacingAngle(angleToTarget);

        UpdateCamera((self.WorldAimingTarget - self.Player.Position).Normalised() * 20);

        self.aimingTarget.X = Input.MouseX;
        self.aimingTarget.Y = Input.MouseY;
